let message = ""
/**
 * ! !!!!!!
 * 以下为凶残的cron表达式验证，胆小肾虚及心脏病者慎入!!!
 * 不听劝告者后果自负T T
 * !!!!!!!
 * cron表达式为秒，分，时，日，月，周，年
 * 判断正误方法：错误的话返回错误信息，正确的话返回true
 * @param {string | true}cronExpression crom表达式
 */
export default function cronValidate(cronExpression) {
  // 先将cron表达式进行分割
  let cronParams = cronExpression.split(" ")
  // 判断cron表达式是否具有该具有的属性长度，没有年份的长度为6，带年份的长度为7，其他情况都是错误的
  if (cronParams.length < 6 || cronParams.length > 7) {
    return "cron表达式需要输入6-7位参数，请重新输入"
  } else {
    // 日和周必须有一个为?，或者全为*
    if ((cronParams[3] == "?" && cronParams[5] != "?") || (cronParams[5] == "?" && cronParams[3] != "?") || (cronParams[3] == "*" && cronParams[5] == "*")) {
      // 检查第一位的秒是否正确
      message = checkSecondsField(cronParams[0])
      if (message != true) {
        return message
      }

      // 检查第二位的分是否正确
      message = checkMinutesField(cronParams[1])
      if (message != true) {
        return message
      }

      // 检查第三位的时是否正确
      message = checkHoursField(cronParams[2])
      if (message != true) {
        return message
      }

      // 检查第四位的日是否正确
      message = checkDayOfMonthField(cronParams[3])
      if (message != true) {
        return message
      }

      // 检查第五位的月是否正确
      message = checkMonthsField(cronParams[4])
      if (message != true) {
        return message
      }

      // 检查第6位的周是否正确
      message = checkDayOfWeekField(cronParams[5])
      if (message != true) {
        return message
      }

      // 检查第七位的年是否正确
      if (cronParams.length > 6) {
        message = checkYearField(cronParams[6])
        if (message != true) {
          return message
        }
      }

      return true
    } else {
      return "指定日时周必须设为不指定(?),指定周时日必须设为不指定(?)"
    }
  }
}

// 检查秒的函数方法
/**
 *
 * @param secondsField
 */
function checkSecondsField(secondsField) {
  return checkField(secondsField, 0, 59, "秒")
}

// 检查分的函数方法
/**
 *
 * @param minutesField
 */
function checkMinutesField(minutesField) {
  return checkField(minutesField, 0, 59, "分")
}

// 检查小时的函数方法
/**
 *
 * @param hoursField
 */
function checkHoursField(hoursField) {
  return checkField(hoursField, 0, 23, "时")
}

// 检查日期的函数方法
/**
 *
 * @param dayOfMonthField
 */
function checkDayOfMonthField(dayOfMonthField) {
  if (dayOfMonthField == "?") {
    return true
  }
  if (dayOfMonthField.indexOf("L") >= 0) {
    return checkFieldWithLetter(dayOfMonthField, "L", 1, 7, "日")
  } else if (dayOfMonthField.indexOf("W") >= 0) {
    return checkFieldWithLetter(dayOfMonthField, "W", 1, 31, "日")
  } else if (dayOfMonthField.indexOf("C") >= 0) {
    return checkFieldWithLetter(dayOfMonthField, "C", 1, 31, "日")
  }
  return checkField(dayOfMonthField, 1, 31, "日")
}

// 检查月份的函数方法
/**
 *
 * @param monthsField
 */
function checkMonthsField(monthsField) {
  // 月份简写处理
  if (monthsField != "*") {
    monthsField = monthsField.replace("JAN", "1")
    monthsField = monthsField.replace("FEB", "2")
    monthsField = monthsField.replace("MAR", "3")
    monthsField = monthsField.replace("APR", "4")
    monthsField = monthsField.replace("MAY", "5")
    monthsField = monthsField.replace("JUN", "6")
    monthsField = monthsField.replace("JUL", "7")
    monthsField = monthsField.replace("AUG", "8")
    monthsField = monthsField.replace("SEP", "9")
    monthsField = monthsField.replace("OCT", "10")
    monthsField = monthsField.replace("NOV", "11")
    monthsField = monthsField.replace("DEC", "12")
    return checkField(monthsField, 1, 12, "月份")
  } else {
    return true
  }
}

// 星期验证
/**
 *
 * @param dayOfWeekField
 */
function checkDayOfWeekField(dayOfWeekField) {
  dayOfWeekField = dayOfWeekField.replace("SUN", "1")
  dayOfWeekField = dayOfWeekField.replace("MON", "2")
  dayOfWeekField = dayOfWeekField.replace("TUE", "3")
  dayOfWeekField = dayOfWeekField.replace("WED", "4")
  dayOfWeekField = dayOfWeekField.replace("THU", "5")
  dayOfWeekField = dayOfWeekField.replace("FRI", "6")
  dayOfWeekField = dayOfWeekField.replace("SAT", "7")
  if (dayOfWeekField == "?") {
    return true
  }
  if (dayOfWeekField.indexOf("L") >= 0) {
    return checkFieldWithLetterWeek(dayOfWeekField, "L", 1, 7, "星期")
  } else if (dayOfWeekField.indexOf("C") >= 0) {
    return checkFieldWithLetterWeek(dayOfWeekField, "C", 1, 7, "星期")
  } else if (dayOfWeekField.indexOf("#") >= 0) {
    return checkFieldWithLetterWeek(dayOfWeekField, "#", 1, 7, "星期")
  } else {
    return checkField(dayOfWeekField, 1, 7, "星期")
  }
}

// 检查年份的函数方法
/**
 *
 * @param yearField
 */
function checkYearField(yearField) {
  return checkField(yearField, 1970, 2099, "年的")
}

// 通用的检查值的大小范围的方法( - , / *)
/**
 *
 * @param value
 * @param minimal
 * @param maximal
 * @param attribute
 */
function checkField(value, minimal, maximal, attribute) {
  // 校验值中是否有“-”，如果有“-”的话，下标会>0
  if (value.indexOf("-") > -1) {
    return checkRangeAndCycle(value, minimal, maximal, attribute)
  } else if (value.indexOf(",") > -1) {
    // 校验值中是否有“，”，如果有“,”的话，下标会>0
    return checkListField(value, minimal, maximal, attribute)
  } else if (value.indexOf("/") > -1) {
    // 校验值中是否有“/”，如果有“/”的话，下标会>0
    return checkIncrementField(value, minimal, maximal, attribute)
  } else if (value == "*") {
    // 校验值是否为“*”
    return true
  } else {
    // 校验单独的数字，英文字母，以及各种神奇的符号等...
    return checkIntValue(value, minimal, maximal, true, attribute)
  }
}

// 检测是否是整数以及是否在范围内,参数：检测的值，下限，上限，是否检查端点，检查的属性
/**
 *
 * @param value
 * @param minimal
 * @param maximal
 * @param checkExtremity
 * @param attribute
 */
function checkIntValue(value, minimal, maximal, checkExtremity, attribute) {
  try {
    // 用10进制犯法来进行整数转换
    let val = parseInt(value, 10)
    if (value == val) {
      if (checkExtremity) {
        if (val < minimal || val > maximal) {
          return (attribute + "的参数取值范围必须在" + minimal + "-" + maximal + "之间")
        }
        return true
      }
      return true
    }
    return (attribute + "的参数存在非法字符，必须为整数或允许的大写英文")
  } catch (e) {
    return (attribute + "的参数有非法字符，必须是整数~")
  }
}
// 检验枚举类型的参数是否正确
/**
 *
 * @param value
 * @param minimal
 * @param maximal
 * @param attribute
 */
function checkListField(value, minimal, maximal, attribute) {
  let st = value.split(",")
  let values = new Array(st.length)
  // 计算枚举的数字在数组中中出现的次数，出现一次为没有重复的。
  let count = 0
  for (let j = 0; j < st.length; j++) {
    values[j] = st[j]
  }
  // 判断枚举类型的值是否重复
  for (let i = 0; i < values.length; i++) {
    // 判断枚举的值是否在范围内
    message = checkIntValue(values[i], minimal, maximal, true, attribute)
    if (message != true) {
      return message
    }
    count = 0
    for (let j = 0; j < values.length; j++) {
      if (values[i] == values[j]) {
        count++
      }
      if (count > 1) {
        return (attribute + "中的参数重复")
      }
    }
  }
  let previousValue = -1
  // 判断枚举的值是否排序正确
  for (let i = 0; i < values.length; i++) {
    let currentValue = values[i]
    try {
      let val = parseInt(currentValue, 10)
      if (val < previousValue) {
        return (attribute + "的参数应该从小到大")
      } else {
        previousValue = val
      }
    } catch (e) {
      // 前面验证过了，这边的代码不可能跑到
      return ("这段提示用不到")
    }
  }
  return true
}

// 检验循环
/**
 *
 * @param value
 * @param minimal
 * @param maximal
 * @param attribute
 */
function checkIncrementField(value, minimal, maximal, attribute) {
  if (value.split("/").length > 2) {
    return (attribute + "中的参数只能有一个'/'")
  }
  let start = value.substring(0, value.indexOf("/"))
  let increment = value.substring(value.indexOf("/") + 1)
  if (start != "*") {
    // 检验前值是否正确
    message = checkIntValue(start, minimal, maximal, true, attribute)
    if (message != true) {
      return message
    }
    // 检验后值是否正确
    message = checkIntValue(increment, minimal, maximal, true, attribute)
    if (message != true) {
      return message
    }
    return true
  } else {
    // 检验后值是否正确
    return checkIntValue(increment, minimal, maximal, false, attribute)
  }
}

// 检验范围
/**
 *
 * @param params
 * @param minimal
 * @param maximal
 * @param attribute
 */
function checkRangeAndCycle(params, minimal, maximal, attribute) {
  // 校验“-”符号是否只有一个
  if (params.split("-").length > 2) {
    return (attribute + "中的参数只能有一个'-'")
  }
  let value = null
  let cycle = null
  // 检验范围内是否有嵌套周期
  if (params.indexOf("/") > -1) {
    // 校验“/”符号是否只有一个
    if (params.split("/").length > 2) {
      return (attribute + "中的参数只能有一个'/'")
    }
    value = params.split("/")[0]
    cycle = params.split("/")[1]
    // 判断循环的参数是否正确
    message = checkIntValue(cycle, minimal, maximal, true, attribute)
    if (message != true) {
      return message
    }
  } else {
    value = params
  }
  let startValue = value.substring(0, value.indexOf("-"))
  let endValue = value.substring(value.indexOf("-") + 1)
  // 判断参数范围的第一个值是否正确
  message = checkIntValue(startValue, minimal, maximal, true, attribute)
  if (message != true) {
    return message
  }
  // 判断参数范围的第二个值是否正确
  message = checkIntValue(endValue, minimal, maximal, true, attribute)
  if (message != true) {
    return message
  }
  // 判断参数的范围前值是否小于后值
  try {
    let startVal = parseInt(startValue, 10)
    let endVal = parseInt(endValue, 10)
    if (endVal < startVal) {
      return (attribute + "的取值范围错误，前值必须小于后值")
    }
    if ((endVal - startVal) < parseInt(cycle, 10)) {
      return (attribute + "的取值范围内的循环无意义")
    }
    return true
  } catch (e) {
    // 用不到这行代码的
    return (attribute + "的参数有非法字符，必须是整数")
  }
}

// 检查日中的特殊字符
/**
 *
 * @param value
 * @param letter
 * @param minimalBefore
 * @param maximalBefore
 * @param attribute
 */
function checkFieldWithLetter(value, letter, minimalBefore, maximalBefore, attribute) {
  // 判断是否只有一个字母
  for (let i = 0; i < value.length; i++) {
    let count = 0
    if (value.charAt(i) == letter) {
      count++
    }
    if (count > 1) {
      return (attribute + "的值的" + letter + "字母只能有一个")
    }
  }
  // 校验L
  if (letter == "L") {
    if (value == "LW") {
      return true
    }
    if (value == "L") {
      return true
    }
    if (value.endsWith("LW") && value.length > 2) {
      return (attribute + "中的参数，最后的LW前面不能有任何字母参数")
    }
    if (!value.endsWith("L")) {
      return (attribute + "中的参数，L字母后面不能有W以外的字符、数字等")
    } else {
      let num = value.substring(0, value.indexOf(letter))
      return checkIntValue(num, minimalBefore, maximalBefore, true, attribute)
    }
  }

  // 校验W
  if (letter == "W") {
    if (!value.endsWith("W")) {
      return (attribute + "中的参数的W必须作为结尾")
    } else {
      if (value == "W") {
        return (attribute + "中的参数的W前面必须有数字")
      }
      let num = value.substring(0, value.indexOf(letter))
      return checkIntValue(num, minimalBefore, maximalBefore, true, attribute)
    }
  }

  if (letter == "C") {
    if (!value.endsWith("C")) {
      return (attribute + "中的参数的C必须作为结尾")
    } else {
      if (value == "C") {
        return (attribute + "中的参数的C前面必须有数字")
      }
      let num = value.substring(0, value.indexOf(letter))
      return checkIntValue(num, minimalBefore, maximalBefore, true, attribute)
    }
  }
}

// 检查星期中的特殊字符
/**
 *
 * @param value
 * @param letter
 * @param minimalBefore
 * @param maximalBefore
 * @param attribute
 */
function checkFieldWithLetterWeek(value, letter, minimalBefore, maximalBefore, attribute) {
  // 判断是否只有一个字母
  for (let i = 0; i < value.length; i++) {
    let count = 0
    if (value.charAt(i) == letter) {
      count++
    }
    if (count > 1) {
      return (attribute + "的值的" + letter + "字母只能有一个")
    }
  }
  // 校验L
  if (letter == "L") {
    if (value == "L") {
      return true
    }
    if (!value.endsWith("L")) {
      return (attribute + "中的参数，L字母必须是最后一位")
    } else {
      let num = value.substring(0, value.indexOf(letter))
      return checkIntValue(num, minimalBefore, maximalBefore, true, attribute)
    }
  }

  if (letter == "C") {
    if (!value.endsWith("C")) {
      return (attribute + "中的参数的C必须作为结尾")
    } else {
      if (value == "C") {
        return (attribute + "中的参数的C前面必须有数字")
      }
      let num = value.substring(0, value.indexOf(letter))
      return checkIntValue(num, minimalBefore, maximalBefore, true, attribute)
    }
  }

  if (letter == "#") {
    if (value == "#") {
      return (attribute + "中的#前后必须有整数")
    }
    if (value.charAt(0) == letter) {
      return (attribute + "中的#前面必须有整数")
    }
    if (value.endsWith("#")) {
      return (attribute + "中的#后面必须有整数")
    }
    let num1 = value.substring(0, value.indexOf(letter))
    let num2 = value.substring(value.indexOf(letter) + 1, value.length)
    message = checkIntValue(num1, 1, 4, true, (attribute + "的#前面"))
    if (message != true) {
      return message
    }
    message = checkIntValue(num2, minimalBefore, maximalBefore, true, (attribute + "的#后面"))
    if (message != true) {
      return message
    }
    return true
  }
}
